﻿using ApplicationManager.Model;
using DingGC.Library.Cache;
using DingGC.Library.Common;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using SharpCompress.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace ApplicationManager.Services
{
    public class MitmProxyAppService
    {
        private string key = "mitmproxyapps";
        private readonly ICache<RocksCache> cache;
        private readonly IConfiguration configuration;
        private readonly ILogger<MitmProxyAppService> logger;

        public MitmProxyAppService(ICache<RocksCache> cache, IConfiguration configuration
            , ILogger<MitmProxyAppService> logger)
        {
            this.cache = cache;
            this.configuration = configuration;
            this.logger = logger;
        }

        /// <summary>
        /// 启动进程
        /// </summary>
        /// <param name="appInfo"></param>
        /// <returns></returns>
        public async Task<bool> Create(MitmProxyAppInfoRequest request)
        {
            try
            {
                string mitmproxyPath = configuration.GetValue<string>("MitmProxyPath");
                bool UseShellExecute = configuration.GetValue<bool>("UseShellExecute");
                string pythonPath = configuration.GetValue<string>("PythonPath");
                int port = request.Port;
                if (port <= 0)
                {
                    port = PortUtils.GetAvailablePort();
                }

                var process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = mitmproxyPath,
                        Arguments = $"-p {port} -s {pythonPath} --mode upstream:http://{request.ProxyIP}:{request.ProxyPort} --set upstream_auth={request.ProxyUserName}:{request.ProxyPassword} --set block_global=false ",
                        //RedirectStandardOutput = true,
                        //RedirectStandardError = true,
                        UseShellExecute = true,
                        CreateNoWindow = true
                    }
                };


                // 启动进程  
                process.Start();
                Thread.Sleep(500);

                MitmProxyAppInfoModel model = AutoMapperHelper<MitmProxyAppInfoRequest, MitmProxyAppInfoModel>.MapTo(request);
                model.ProcessId = process.Id;
                model.Port = port;

                List<MitmProxyAppInfoModel> appInfoModels = GetAppInfos();

                appInfoModels.Insert(0, model);
                SaveAppInfo(appInfoModels);
                Task.Run(() => GetSubProcessStatus(model, appInfoModels));
                return GetAppStatus(model.ProcessId);

            }
            catch (System.Exception ex)
            {
                logger.LogError(ex, "创建应用异常");
                return false;

            }


        }

        /// <summary>
        ///  启动应用程序  
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> Start(string id)
        {
            List<MitmProxyAppInfoModel> appInfoModels = GetAppInfos();
            var appInfo = appInfoModels.Where(p => p.Id == id).FirstOrDefault();

            string mitmproxyPath = configuration.GetValue<string>("MitmProxyPath");
            string pythonPath = configuration.GetValue<string>("PythonPath");
            string directoryPath = Path.GetDirectoryName(pythonPath);
            int port = appInfo.Port;// PortUtils.GetAvailablePort();
            logger.LogInformation($"{mitmproxyPath} -p {port} -s {pythonPath} --mode upstream:http://{appInfo.ProxyIP}:{appInfo.ProxyPort} --set upstream_auth={appInfo.ProxyUserName}:{appInfo.ProxyPassword} --set block_global=false");
            var process = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = mitmproxyPath,
                    Arguments = $"-p {port} -s {pythonPath} --mode upstream:http://{appInfo.ProxyIP}:{appInfo.ProxyPort} --set upstream_auth={appInfo.ProxyUserName}:{appInfo.ProxyPassword} --set block_global=false  ",
                    //RedirectStandardOutput = true,
                    //RedirectStandardError = true,
                    WorkingDirectory = directoryPath,
                    UseShellExecute = true,
                    CreateNoWindow = true
                }
            };
            // 启动进程  
            process.Start();
            Thread.Sleep(500);
            //// 输出 mitmDump 的标准输出和错误  
            //string output = process.StandardOutput.ReadToEnd();
            //string error = process.StandardError.ReadToEnd();

            //// 保持程序运行，直到 mitmDump 进程退出  
            //process.WaitForExit();

            //// 在 mitmDump 退出后处理  
            //Console.WriteLine("mitmdump exited.");
            //Console.WriteLine("Output: " + output);
            //Console.WriteLine("Error: " + error);
            appInfo.ProcessId = process.Id;
            SaveAppInfo(appInfoModels);
            Task.Run(() => GetSubProcessStatus(appInfo, appInfoModels));
            return GetAppStatus(appInfo.ProcessId);
        }

        /// <summary>
        /// Stop app
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> Stop(string id)
        {
            var appInfos = GetAppInfos();
            MitmProxyAppInfoModel appInfo = appInfos.FirstOrDefault(p => p.Id == id);
            if (appInfo == null)
                return false;
            KillApp(appInfo.ProcessId);
            return true;
        }

        /// <summary>
        /// 删除进程
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> Delete(string id)
        {
            var appInfos = GetAppInfos();
            if (appInfos == null || appInfos.Count == 0)
                return false;
            MitmProxyAppInfoModel appInfo = appInfos.FirstOrDefault(p => p.Id == id);
            if (appInfo == null)
                return false;
            KillApp(appInfo.ProcessId);
            appInfos.Remove(appInfo);
            SaveAppInfo(appInfos);
            return true;
        }


        /// <summary>
        /// 返回进程状态
        /// </summary>
        /// <returns></returns>
        public async Task<List<MitmProxyAppInfoResponse>> GetAppStatus()
        {
           // await Console.Out.WriteLineAsync(  $"进程6520的父进程为 {ProcessHelper.GetParentProcessId(Process.GetProcessById(6520))}" );


            var appModels = GetAppInfos();
            List<MitmProxyAppInfoResponse> responses = new List<MitmProxyAppInfoResponse>();
            Process[] allProcesses = Process.GetProcesses();
            foreach (var model in appModels)
            {
                var response = AutoMapperHelper<MitmProxyAppInfoModel, MitmProxyAppInfoResponse>.MapTo(model);
                responses.Add(response);
                response.IPPort = configuration.GetValue<string>("IP") + ":" + model.Port;
                var process = GetProcesses(response.ProcessId);
                //var process = GetProcesses(34856);

                if (process != null)
                {
                    response.Status = true;


                    response.MemoryUsage = process.WorkingSet64 / (1024 * 1024);
                   // logger.LogInformation($"进程{response.ProcessId} 有{model.SubProcessIds.Count}子进程");
                    if (model.SubProcessIds.Count > 0)
                    {

                        foreach (var subid in model.SubProcessIds)
                        {
                            var subProcess = GetProcesses(subid);
                            if (subProcess != null)
                            {
                                var mUsage = subProcess.WorkingSet64 / (1024 * 1024);
                                logger.LogInformation($"子进程{subProcess.Id} 占用{mUsage}M");
                                if (mUsage > response.MemoryUsage)
                                {
                                    response.MemoryUsage = mUsage;
                                }

                            }
                                
                        }
                       
                    }
                 
                }
                else
                {
                    response.Status = false;
                    response.MemoryUsage = 0;
                }

            }
            return responses;
        }


        private List<MitmProxyAppInfoModel> GetAppInfos()
        {
            List<MitmProxyAppInfoModel> list = null;
            if (cache.Exists(key))
            {
                list = cache.Get<List<MitmProxyAppInfoModel>>(key);
                return list;
            }
            list = new List<MitmProxyAppInfoModel>();
            return list;
        }

        private MitmProxyAppInfoModel GetAppInfo(string id)
        {
            if (cache.Exists(key))
            {
                var list = cache.Get<List<MitmProxyAppInfoModel>>(key);
                var appinfo = list.FirstOrDefault(p => p.Id == id);
                return appinfo;

            }

            return null;
        }
        /// <summary>
        /// 获取进程状态
        /// </summary>
        /// <param name="processid"></param>
        /// <returns></returns>
        private bool GetAppStatus(int processid)
        {
            var processes = Process.GetProcesses(); // 获取所有当前运行的进程  
            var process = processes.FirstOrDefault(p => p.Id == processid);
            if (process != null)
            {
                return true;

            }
            return false;
        }

        private Process GetProcesses(int processid)
        {
            var processes = Process.GetProcesses(); // 获取所有当前运行的进程  
            var process = processes.FirstOrDefault(p => p.Id == processid);
            return process;
        }

        /// <summary>
        /// 杀死进程
        /// </summary>
        /// <param name="processid"></param>
        /// <returns></returns>
        private bool KillApp(int processid)
        {
            var processes = Process.GetProcesses(); // 获取所有当前运行的进程  
            var process = processes.FirstOrDefault(p => p.Id == processid);
            if (process != null)
            {
                process.Kill();

            }
            return true;

        }


        private bool SaveAppInfo(List<MitmProxyAppInfoModel> appInfos)
        {
            cache.Set(key, appInfos);
            return true;
        }


        private void GetSubProcessStatus(MitmProxyAppInfoModel appinfo , List<MitmProxyAppInfoModel> appInfos)
        {
            Thread.Sleep(3000);
            appinfo.SubProcessIds.Clear();
            var subs = ProcessHelper.GetChildProcessesCsv(appinfo.ProcessId);
            if (subs != null && subs.Count > 0)
            {
                
                appinfo.SubProcessIds.AddRange(subs.Select(p => p).ToList());
                SaveAppInfo(appInfos);
            }
           
        }


        public async Task CheckMemory()
        {
            int maxmemory = configuration.GetValue<int>("MaxMemory");
            if (maxmemory == 0) maxmemory = 500;
            var apps = GetAppInfos();
            //获取所有python.exe的进程，判断apps里面是不是少了对应的进程
            var commandLines=ProcessHelper.GetProcessesAlternative("python.exe");
            commandLines.AddRange( ProcessHelper.GetProcessesAlternative("mitmdump.exe"));
            Dictionary<int,List<int>> processIDs=new Dictionary<int, List<int>>();
            foreach (var cmd in commandLines)
            {
                if (cmd.ProcessId > 0 && !string.IsNullOrWhiteSpace(cmd.CommandLine))
                {
                    string pattern = @"-p\s+(\d+)";
                    Match match = Regex.Match(cmd.CommandLine, pattern);

                    if (match.Success && match.Groups.Count > 1)
                    {
                        int prot = 0;
                        if (int.TryParse(match.Groups[1].Value, out prot))
                        {
                            var app = apps.FirstOrDefault(p => p.Port == prot);
                            if (app != null && app.ProcessId!= cmd.ProcessId && ! app.SubProcessIds.Contains(cmd.ProcessId) )
                            {
                                app.SubProcessIds.Add(cmd.ProcessId);
                            }
                        }
                    }
                }
              
            }

            foreach (var app in apps)
            {
                long appMemoryUsage = 0;
                var process = GetProcesses(app.ProcessId);
                if (process != null)
                {
                    appMemoryUsage = process.WorkingSet64 / (1024 * 1024);
                    if (app.SubProcessIds.Count > 0)
                    {
                        foreach (var subid in app.SubProcessIds)
                        {
                            var subProcess = GetProcesses(subid);
                            if (subProcess != null)
                            {
                                var mUsage = subProcess.WorkingSet64 / (1024 * 1024);
                                if (mUsage > appMemoryUsage)
                                {
                                    appMemoryUsage = mUsage;
                                }

                            }

                        }

                    }
                }
                if (appMemoryUsage > maxmemory)
                {
                    logger.LogInformation($"内存占用过大，重启任务{app.Name}");
                    await Stop(app.Id);
                    Thread.Sleep(1000);
                    await Start(app.Id);
                }
            }

            //检查所有python.exe 进程内存是否过大
            var processes = Process.GetProcesses();



        }



    }

}
